﻿﻿using System;

namespace MTBase
{
    public enum TimerType
    {
        //时间
        Time,
        //帧
        Frame,
    }
    
    /// <summary>
    /// 定时器抽象实体
    /// </summary>
    internal abstract class AbsTimerData:PoolObject
    {
        

        protected abstract Pool Pool { get; }
        private uint m_nTimerId;

        public uint NTimerId
        {
            get { return m_nTimerId; }
            set { m_nTimerId = value; }
        }
        private int m_nInterval;

        public int NInterval
        {
            get { return m_nInterval; }
            set { m_nInterval = value; }
        }
        private ulong m_unNextTick;

        public ulong UnNextTick
        {
            get { return m_unNextTick; }
            set { m_unNextTick = value; }
        }

        /// <summary>
        /// 是否开启追时间处理
        /// 大致: 当用户切到后台之后比如5个小时 再切回前台的时候，本次流逝时间就是5小时， 如果注册的timer是10分钟
        /// 如果设置为true， 那么10分钟的timer会调用 5*60 / 10 次
        /// 如果设置为false， 只会触发一次， 然后继续以 当前时间 + 10 注册下一次的调用。
        /// 默认为false
        /// </summary>
        public bool needTimeChasing = false;

        public int recordCount  = 0;
        public int maxCount = 0;

        public abstract Delegate Action
        {
            get;
            set;
        }

        public TimerType TimerType;
        

        public abstract void DoAction();

        public virtual void Release()
        {
            Pool.Push(this);
        }

        public abstract void OnPush();
    }

    /// <summary>
    /// 无参数定时器实体
    /// </summary>
    internal class TimerData : AbsTimerData
    {
        private static QueuePool pool = new QueuePool(() => { return new TimerData(); });
        private Action m_action;

        protected override Pool Pool
        {
            get { return pool; }
        }

        public override Delegate Action
        {
            get { return m_action; }
            set { m_action = value as Action; }
        }

        public override void DoAction()
        {
            m_action();
        }
        public override void OnPush()
        {
            m_action = null;
            recordCount = 0;
        }
        
        public override void Release()
        {
            Pool.Push(this);
        }

        public static TimerData Get()
        {
            return pool.Pop() as TimerData;
        }

    }

    /// <summary>
    /// 1个参数定时器实体
    /// </summary>
    /// <typeparam name="T">参数1</typeparam>
    internal class TimerData<T> : AbsTimerData
    {
        private static QueuePool pool = new QueuePool(() => { return new TimerData(); });
        private Action<T> m_action;

        protected override Pool Pool
        {
            get { return pool; }
        }

        public override Delegate Action
        {
            get { return m_action; }
            set { m_action = value as Action<T>; }
        }

        private T m_arg1;

        public T Arg1
        {
            get { return m_arg1; }
            set { m_arg1 = value; }
        }

        public override void DoAction()
        {
            m_action(m_arg1);
        }

        public override void OnPush()
        {
            m_action = null;
            Arg1 = default(T);
            recordCount = 0;
        }
        
        public override void Release()
        {
            Pool.Push(this);
        }

        public static TimerData<T> Get()
        {
            return pool.Pop() as TimerData<T>;
        }
    }

    /// <summary>
    /// 2个参数定时器实体
    /// </summary>
    /// <typeparam name="T">参数1</typeparam>
    /// <typeparam name="U">参数2</typeparam>
    internal class TimerData<T, U> : AbsTimerData
    {
        private static QueuePool pool = new QueuePool(() => { return new TimerData(); });
        private Action<T, U> m_action;

        protected override Pool Pool
        {
            get { return pool; }
        }

        public override Delegate Action
        {
            get { return m_action; }
            set { m_action = value as Action<T, U>; }
        }

        private T m_arg1;

        public T Arg1
        {
            get { return m_arg1; }
            set { m_arg1 = value; }
        }

        private U m_arg2;

        public U Arg2
        {
            get { return m_arg2; }
            set { m_arg2 = value; }
        }

        public override void DoAction()
        {
            m_action(m_arg1, m_arg2);
        }
        public override void OnPush()
        {
            m_action = null;
            Arg1 = default(T);
            Arg2 = default(U);
            recordCount = 0;
        }
        
        public override void Release()
        {
            Pool.Push(this);
        }
        
        public static TimerData<T, U> Get()
        {
            return pool.Pop() as TimerData<T, U>;
        }
    }

    /// <summary>
    /// 3个参数定时器实体
    /// </summary>
    /// <typeparam name="T">参数1</typeparam>
    /// <typeparam name="U">参数2</typeparam>
    /// <typeparam name="V">参数3</typeparam>
    internal class TimerData<T, U, V> : AbsTimerData
    {
        private static QueuePool pool = new QueuePool(() => { return new TimerData(); });
        private Action<T, U, V> m_action;

        protected override Pool Pool
        {
            get { return pool; }
        }

        public override Delegate Action
        {
            get { return m_action; }
            set { m_action = value as Action<T, U, V>; }
        }

        private T m_arg1;

        public T Arg1
        {
            get { return m_arg1; }
            set { m_arg1 = value; }
        }

        private U m_arg2;

        public U Arg2
        {
            get { return m_arg2; }
            set { m_arg2 = value; }
        }

        private V m_arg3;

        public V Arg3
        {
            get { return m_arg3; }
            set { m_arg3 = value; }
        }

        public override void DoAction()
        {
            m_action(m_arg1, m_arg2, m_arg3);
        }

        public override void OnPush()
        {
            m_action = null;
            Arg1 = default(T);
            Arg2 = default(U);
            Arg3 = default(V);
            recordCount = 0;
        }
        
        public override void Release()
        {
            Pool.Push(this);
        }

        public static TimerData<T, U, V> Get()
        {
            return pool.Pop() as TimerData<T, U, V>;
        }
    }

}